Public Class frmDBExplorer
    Const TrackingWarning = vbCr & vbCr & "(Note that Tracking table records are automatically changed to reflect the results of this operation.)"
    Private WithEvents bwExecuteNonQuery As System.ComponentModel.BackgroundWorker
    Private QuerySQL As String 'so completed event has access to SQL string
    Private PriorTimeout As Integer
    Private ErrorAlreadyDisplayed As Boolean = False
    Dim dgvResults As WRDB.Controls.DGVEditor

    Private Enum enumIndexAction
        None
        Create
        Drop
    End Enum

    Private Function fixLikeWildcards(ByVal s As String) As String
        Dim pos As Integer = s.ToUpper.IndexOf("LIKE")
        If pos <> -1 Then
            Dim s2 As String = s.Substring(pos)
            s2 = s2.Replace("*", "%")
            s2 = s2.Replace("@", "_")
            s2 = s2.Replace("?", "_")
            s2 = s2.Replace(".%", ".*") 'don't want to substitute like Dta.*
            Return s.Substring(0, pos) & s2
        Else
            Return s
        End If
    End Function

    Private Sub btnChange_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnChange.Click, mnuChange.Click
        Try
            With New frmChangeRecords(lstTables.Text, frmChangeRecords.enumChangeDelete.Change)
                .ShowDialog(Me)
                .Dispose()
            End With
            RefreshAllForms()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub btnClose_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClose.Click
        If Me.lnkProgress.Visible Then AskCancel() : DialogResult = Windows.Forms.DialogResult.None
        MainForm.CheckSupportTablesExist()
    End Sub

    Private Sub btnCompact_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCompact.Click, mnuCompact.Click
        Try

            If WarningMsg("This tool will delete all temporary tables and views from the current database and attempt to perform a database compaction and repair operation (if this data provider supports it). You should only perform this operation when no other users are accessing this database.\n\nAre you sure you want to continue?") = Windows.Forms.DialogResult.Cancel Then Exit Sub

            With Project
                TaskStart("Compacting/repairing database for " & .Name)
                Dim Interactive As Boolean = False
                If .DB.DatabaseType = clsDB.enumDBType.Paradox Then
                    Select Case MessageBox.Show("Do you want to automatically repair all tables in this Project? If you select 'No', you will be able to interactively select the files to repair.", "Compact/Repair", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                        Case Windows.Forms.DialogResult.Yes : Interactive = False
                        Case Windows.Forms.DialogResult.No : Interactive = True
                        Case Else
                            Exit Sub
                    End Select
                End If

                .CleanDatabase() 'clean up current user's tables and views

                'clean up ALL user's temporary tables and views (assume looks like TEMP_ and DATA_)
                Dim TempPrefix As String = clsProject.TempPrefix.Split("_")(0) & "_"
                Dim DataPrefix As String = clsProject.DataPrefix.Split("_")(0) & "_"

                If .DB.SupportsViews Then
                    For Each s As String In .DB.GetViewList
                        If s.StartsWith(TempPrefix, StringComparison.OrdinalIgnoreCase) Then .DB.DropView(s)
                    Next
                End If
                For Each s As String In .DB.GetTableList
                    'GetTableList returns table names in project database and in temp database, but doesn't prefix with database name
                    If clsProject.TempPrefix IsNot Nothing AndAlso clsProject.DataPrefix IsNot Nothing Then
                        If s.StartsWith(TempPrefix, StringComparison.OrdinalIgnoreCase) Then .DB.DropTable(s)
                        If s.StartsWith(DataPrefix, StringComparison.OrdinalIgnoreCase) Then .DB.DropTable(s)
                        s = clsProject.TempDBName & "." & s
                        If s.StartsWith(TempPrefix, StringComparison.OrdinalIgnoreCase) Then .DB.DropTable(s)
                        If s.StartsWith(DataPrefix, StringComparison.OrdinalIgnoreCase) Then .DB.DropTable(s)
                    End If
                Next

                If Interactive Then
                    .DB.RepairDatabase(Interactive)
                Else
                    If .DB.DatabaseType = clsDB.enumDBType.Paradox Then
                        Environment.CurrentDirectory = IO.Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly.Location)
                        Dim LogFile As String = "Pdxrbld.log"
                        If My.Computer.FileSystem.FileExists(LogFile) Then My.Computer.FileSystem.DeleteFile(LogFile)

                        Dim col As New Generic.List(Of String)
                        col.Add(.WorkingDir)
                        If Not col.Contains(.MasterDir) Then col.Add(.MasterDir)
                        If Not col.Contains(.SupportDir) Then col.Add(.SupportDir)
                        If Not col.Contains(.SupportDirProject) Then col.Add(.SupportDirProject)

                        For Each s As String In col
                            .DB.DataSource = s
                            .DB.RepairDatabase(Interactive)
                        Next

                        If My.Computer.FileSystem.FileExists(LogFile) Then Shell("Notepad " & LogFile, AppWinStyle.NormalFocus)
                    Else
                        .DB.RepairDatabase()
                    End If
                End If
            End With
        Catch ex As DbSqlException
            WarningMsg(ex.Message)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnCompare_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCompare.Click, mnuCompare.Click
        Try
            TaskStart("Comparing tables...")
            MainForm.CompareTables(lstTables.SelectedItems(0), lstTables.SelectedItems(1))
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopy.Click, mnuCopy.Click
        Try
            Dim OldName As String = Me.lstTables.SelectedItem
            If Project.GetTableType(OldName) <= clsProject.enumTableTypes.Working Then
                Dim MustBeUpdateable As Boolean = Project.DB.IsTableIndexed(OldName)
                If Not MainForm.CheckDataTableStructure(OldName, MustBeUpdateable) Then Exit Sub
            Else
                If Not MainForm.CheckTableStructure(OldName) Then Exit Sub
            End If
            Dim NewName As String = InputBox("Enter the new name for the copy of the table:  " & TrackingWarning, "Copy Table", OldName)
            If NewName = "" Then Exit Sub
            TaskStart(String.Format("Copying {0} to {1}", OldName, NewName))
            Project.CopyTable(NewName, OldName)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
            FillTableList()
        End Try
    End Sub

    Private Sub btnCopyFrom_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCopyFrom.Click, mnuCopyFrom.Click
        Try
            With New frmCopyTables
                If .ShowDialog(Me) = Windows.Forms.DialogResult.OK AndAlso .lstTables.SelectedItems.Count > 0 Then
                    If MessageBox.Show("Are you sure to want to copy all tables, and rename them in the process? Note that any existing table in your project with the new name will not be overwritten or updated; rather, a new table with the prefix 'Copy_of_' will be created.", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) = Windows.Forms.DialogResult.Cancel Then Exit Sub
                    For Each s As String In .lstTables.SelectedItems
                        Dim DestTable As String
                        If .txtReplace.Text.Trim = "" Then
                            DestTable = .txtWith.Text & s
                        Else
                            DestTable = s.Replace(.txtReplace.Text, .txtWith.Text).Replace(.txtReplace.Text.ToLower, .txtWith.Text).Replace(.txtReplace.Text.ToUpper, .txtWith.Text)
                        End If
                        If Not MainForm.WriteProgress(String.Format("Copying {0} in {1} to {2} in {3}...", s, .cboProject.Text, DestTable, Project.Name), ProgressBarStyle.Marquee) Then Exit For
                        TaskStart(String.Format("Copying {0} in {1} to {2} in {3}", s, .cboProject.Text, DestTable, Project.Name))
                        If .cboProject.Text = Project.Name Then 'copy within this project
                            Project.CopyTable(DestTable, s, , , False, True)
                        Else
                            If Not MainWRDB.DataProviderAvailable(.cboProject.Text) Then Exit Sub
                            Try
                                OtherProject = New clsProject(.cboProject.Text)
                            Catch ex As DbSqlException
                                WarningMsg(ex.Message)
                                Exit Sub
                            End Try
                            Project.CopyTable(DestTable, s, OtherProject, , False, True)
                        End If
                    Next
                End If
            End With
            FillTableList()
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            MainForm.ProgressComplete()
            TaskEnd()
        End Try
    End Sub

    'Private Sub btnCopyTo_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    '    Dim OtherProject As clsProject
    '    With New frmProject
    '        If .ShowDialog() = DialogResult.Cancel Then Exit Sub
    '        OtherProject = New clsProject(.lvwProjects.SelectedItems(0).Text)
    '        .Dispose()
    '    End With

    '    Dim OldName As String = Me.lstTables.SelectedItem
    '    Dim NewName As String = InputBox("Enter the new name for the copy of the table:  " & TrackingWarning, "Copy Table", OldName)
    '    If NewName = "" Then Exit Sub
    '    With Project.DB
    '        NewName = .GetValidTableName(NewName)
    '        If OtherProject.DB.TableExists(NewName) AndAlso MessageBox.Show("The table " & NewName & " already exists in the destination project; do you want to overwrite it?", "Copy Table To", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) = Windows.Forms.DialogResult.No Then Exit Sub
    '        If Not .CreateTable(NewName, OtherProject.GetTableTemplate(NewName)) Then Exit Sub
    '        OtherProject.CopyTable(NewName, OldName, Project, False)
    '    End With
    'End Sub

    Private Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click, mnuDelete.Click
        Try
            Dim TableList As String = ""
            For Each s As String In lstTables.SelectedItems
                TableList &= "\t" & s & "\n"
            Next
            'If WarningMsgFmt("Are you sure you want to permanently delete the selected tables?\n\n{0}{1}", TableList, TrackingWarning) = Windows.Forms.DialogResult.Cancel Then Exit Sub
            If WarningMsgFmt("Are you sure you want to permanently delete the selected table(s)?\n\n{0}", TableList) = Windows.Forms.DialogResult.Cancel Then Exit Sub
            Dim DeleteTracking As Boolean = False
            If cboTableType.Text = "Working Tables" Then
                Select Case MessageBox.Show("Do you also want to remove all references to the selected Working table(s) in the Tracking table?", "Delete Tables", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
                    Case Windows.Forms.DialogResult.Yes : DeleteTracking = True
                    Case Windows.Forms.DialogResult.No : DeleteTracking = False
                    Case Windows.Forms.DialogResult.Cancel : Exit Sub
                End Select
            End If
            Dim SelItems(Me.lstTables.SelectedItems.Count - 1) As String
            Me.lstTables.SelectedItems.CopyTo(SelItems, 0)
            For Each OldName As String In SelItems
                TaskStart(String.Format("Deleting {0}", OldName))
                If Not Project.ResetPDox(OldName) Then Exit Sub
                Project.CleanDatabase() 'in case any view points to this table
                Project.DeleteTable(OldName, DeleteTracking)
                'see if any browser points to old tablename; if so close 
                For Each f As Form In WRDBForms
                    If TypeOf f Is frmBrowser Then
                        With CType(f, frmBrowser)
                            If String.Compare(.TableName, OldName, True) = 0 Or .TableType = clsProject.enumTableTypes.Temporary Then f.Close()
                        End With
                    End If
                Next
            Next
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            FillTableList()
            TaskEnd()
            If Project.DB.TableExists("PCode") Then RefreshAllForms() 'browsers require PCode table when refreshing
        End Try
    End Sub

    Private Sub btnDeleteDuplicates_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDeleteDups.Click, mnuDeleteDups.Click
        Try
            TaskStart("Deleting duplicates...")
            MainForm.FileMgmtDeleteDuplicates(lstTables.SelectedItem)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
            RefreshAllForms()
        End Try
    End Sub

    Private Sub btnDeleteRecords_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDeleteRecords.Click, mnuDeleteRecords.Click
        Try
            MainForm.EditDeleteRecords(lstTables.SelectedItem)
            RefreshAllForms()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub btnExecute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExecute.Click
        Try
            'try to find tablename in statement
            TaskStart("Executing Query...")
            Dim TableName As String = ""
            Dim ar() As String = txtSQL.Text.Split(" ")
            For i As Integer = 0 To ar.Length - 2
                If ar(i).ToUpper = "FROM" Or ar(i).ToUpper = "UPDATE" Or ar(i).ToUpper = "INTO" Then
                    TableName = ar(i + 1)
                    Exit For
                End If
            Next
            If TableName <> "" Then If Not Project.ResetPDox(TableName) Then Exit Sub

            txtSQL.Text = fixLikeWildcards(txtSQL.Text)

            Dim ErrorMsg As String = ""
            'If Not Project.DB.IsSqlValid(txtSQL.Text, ErrorMsg) Then WarningMsg(ErrorMsg, txtSQL.Text) : Exit Sub

            ErrorAlreadyDisplayed = False
            Dim dt As DataTable = Nothing
            If txtSQL.Text.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase) And Not txtSQL.Text.StartsWith("SELECT INTO", StringComparison.OrdinalIgnoreCase) Then
                If Project.DB.AddTable(dt, txtSQL.Text) Then dgResults.DataSource = dt
            Else
                Static AlreadyWarned As Boolean = False
                If Not AlreadyWarned AndAlso WarningMsg("The SQL statement you entered may modify or delete existing tables, and the operation cannot be undone. Are you sure you want to continue?\n\n(This message will not be repeated this session.)") = Windows.Forms.DialogResult.Cancel Then Exit Sub
                AlreadyWarned = True

                Dim NumRec As Integer = Project.DB.ExecuteNonQuery(txtSQL.Text.Replace(vbCrLf, " "))
                If NumRec = -2 Then
                    MessageBox.Show(StringFormat("Query could not be executed; error message was:\n\n{0}", Project.DB.LastException.ToString), "Database Explorer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
                Else
                    MessageBox.Show(StringFormat("Query was successfully executed; {0} records were affected.", NumRec), "Database Explorer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
                End If
                dgResults.DefaultCellStyle.NullValue = "<Null>"
                Dim Sql As String
                Select Case Project.DB.DatabaseType
                    Case clsDB.enumDBType.Firebird, clsDB.enumDBType.Firebird_Embedded
                        Sql = String.Format("SELECT FIRST 1000 * from {0}", Project.DB.FullTableName(TableName))
                    Case clsDB.enumDBType.SQLite, clsDB.enumDBType.MySQL
                        Sql = String.Format("SELECT * FROM {0} LIMIT 1000", Project.DB.FullTableName(TableName))
                    Case clsDB.enumDBType.Oracle
                        Sql = String.Format("SELECT * FROM {0} WHERE CAST(ROWNUM AS INTEGER)<=1000", Project.DB.FullTableName(TableName))
                    Case Else
                        Sql = String.Format("SELECT TOP 1000 * from {0}", Project.DB.FullTableName(TableName))
                End Select
                If TableName <> "" AndAlso Project.DB.AddTable(dt, Sql) Then dgResults.DataSource = dt
            End If
            With dgResults
                For c As Int16 = 0 To .ColumnCount - 1
                    With .Columns(c)
                        .SortMode = DataGridViewColumnSortMode.NotSortable
                        .HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
                        If dgResults.DataSource.Columns(c).DataType Is GetType(String) Then
                            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
                        ElseIf dgResults.DataSource.Columns(c).DataType Is GetType(Boolean) Then
                            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
                        ElseIf dgResults.DataSource.Columns(c).DataType Is GetType(Date) Then
                            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
                            .DefaultCellStyle.Format = MyDateTimeFormat()
                        Else
                            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
                        End If
                        .DefaultCellStyle.NullValue = "<Null>"
                    End With
                Next
                .AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells)
            End With
        Catch ex As DbSqlException
            WarningMsg(ex.Message)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            RefreshAllForms()
            TaskEnd()
        End Try
    End Sub

    Private Sub btnUpgrade_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpgrade.Click, mnuUpgrade.Click
        Try
            Static AlreadyWarned As Boolean = False
            If Not AlreadyWarned AndAlso MessageBox.Show("This routine will upgrade all selected tables to the latest WRDB schema. This will normally be done automatically for you whenever you open a table, however this may be useful to upgrade multiple tables at a time. We recommend that you backup your data before proceeding. Are you sure you want to continue?", "Upgrade Tables", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then Exit Sub
            AlreadyWarned = True
            For Each s As String In lstTables.SelectedItems
                If Not Project.DB.CheckTableStructure(s, Project.GetTableTemplate(s)) Then
                    TaskStart(String.Format("Upgrading table ({0})...", s))
                    Dim MustBeUpgradeable As Boolean = False
                    If Project.DB.DatabaseType = clsDB.enumDBType.Paradox Then MustBeUpgradeable = Project.DB.IsTableIndexed(s)
                    If Project.GetTableType(s) <= clsProject.enumTableTypes.Master Then
                        If Not Project.DB.UpgradeDataTable(s, Project.GetTableTemplate(s), MustBeUpgradeable) Then Exit For
                    Else
                        If Not Project.DB.UpgradeTable(s, Project.GetTableTemplate(s)) Then Exit For
                    End If
                End If
            Next
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExport.Click, mnuExport.Click
        Try
            TaskStart("Exporting table...")
            If lstTables.SelectedItems.Count > 1 Then
                For Each s As String In lstTables.SelectedItems
                    MainForm.OutputExport(s, True, True) 'auto-name exported tables
                Next
                WarningMsgFmt("All exported files are located in: {0}", AppDataPath)
            Else
                MainForm.OutputExport(lstTables.SelectedItems(0), True)
            End If
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnArchive_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnArchive.Click, mnuArchive.Click
        Try
            Dim ZipFile As String
            With New SaveFileDialog
                .AddExtension = True
                .CreatePrompt = False
                .DefaultExt = ".zip"
                .InitialDirectory = AppDataPath
                .FileName = Project.Name & ".zip"
                .Filter = "Archive File (*.zip)|*.zip"
                .SupportMultiDottedExtensions = False
                .OverwritePrompt = False
                .Title = "Select Archive"
                If .ShowDialog(Me) = DialogResult.Cancel Then Exit Sub
                ZipFile = .FileName
            End With

            If My.Computer.FileSystem.FileExists(ZipFile) Then
                Select Case MessageBox.Show(StringFormat("The archive file already exists:\n\n{0}\n\nDo you want to overwrite it?\n\n\t\b Click 'Yes' to overwrite.\n\t\b Click 'No' to append.", ZipFile), "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation)
                    Case Windows.Forms.DialogResult.Yes : My.Computer.FileSystem.DeleteFile(ZipFile)
                    Case Windows.Forms.DialogResult.No
                    Case Windows.Forms.DialogResult.Cancel : Exit Sub
                End Select
            End If

            Dim TempZipPath As String = clsProject.TempPath & "\zip"
            If My.Computer.FileSystem.DirectoryExists(TempZipPath) Then My.Computer.FileSystem.DeleteDirectory(TempZipPath, FileIO.DeleteDirectoryOption.DeleteAllContents)
            My.Computer.FileSystem.CreateDirectory(TempZipPath)
            For Each TableName As String In lstTables.SelectedItems
                TaskStart("Exporting table: " & TableName & "...")
                If Not Project.ExportTable(TableName, TempZipPath & "\" & TableName & ".txt") Then Exit Sub
            Next
            TaskStart("Updating archive file " & IO.Path.GetFileName(ZipFile))
            If My.Computer.FileSystem.FileExists(ZipFile) Then
                Dim z As New ICSharpCode.SharpZipLib.Zip.ZipFile(ZipFile)
                z.BeginUpdate()
                'objective is to add to archive but not include path
                'note: all this code to append to existing zip is quite buggy; got following to work by trial & error
                For Each fn As String In My.Computer.FileSystem.GetFiles(TempZipPath)
                    z.NameTransform = New ICSharpCode.SharpZipLib.Zip.ZipNameTransform(TempZipPath)
                    z.Add(fn)
                Next
                z.CommitUpdate()
                z.Close()
            Else
                Dim fz As New ICSharpCode.SharpZipLib.Zip.FastZip()
                fz.CreateZip(ZipFile, TempZipPath, False, "", "")
            End If
            My.Computer.FileSystem.DeleteDirectory(TempZipPath, FileIO.DeleteDirectoryOption.DeleteAllContents)

        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnImport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnImport.Click, mnuImport.Click
        Try
            Static AlreadyWarned As Boolean = False
            If Not AlreadyWarned AndAlso MessageBox.Show("This routine will attempt to directly import data into the selected table, replacing all records. The import file must be tab-delimited with the appropriate column headings on the first line. Unlike the data import function on the Edit menu, it does no data validation or field mapping (but it is very fast). Are you sure you want to continue?", "Import Text", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then Exit Sub
            AlreadyWarned = True
            TaskStart("Importing table...")
            MainForm.EditImport(lstTables.SelectedItem)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
            RefreshAllForms()
        End Try
    End Sub

    Private Sub btnRename_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRename.Click, mnuRename.Click
        Try
            Dim OldName As String = Me.lstTables.SelectedItem
            Dim NewName As String = InputBox("Enter the new name for the table:  " & TrackingWarning, "Rename Table", OldName)
            If NewName = "" Then Exit Sub
            With Project.DB
                NewName = .GetValidTableName(NewName)
                If NewName = "" Then Exit Sub
                If Not Project.ResetPDox(OldName) Then Exit Sub
                If .TableExists(NewName) Then
                    WarningMsg("A table with that name already exists; you must supply a unique name.")
                ElseIf NewName = OldName Then
                    WarningMsg("You must supply a different name for the table.")
                Else

                    TaskStart(String.Format("Renaming {0} to {1}", OldName, NewName))
                    Project.CleanDatabase() 'in case view refers to old table name
                    Project.RenameTable(OldName, NewName)
                    FillTableList()

                    'see if any browser points to old tablename; if so close and reopen
                    For Each f As Form In WRDBForms
                        If TypeOf f Is frmBrowser Then
                            With CType(f, frmBrowser)
                                If String.Compare(.TableName, OldName, True) = 0 Or .TableType = clsProject.enumTableTypes.Temporary Then f.Close()
                            End With
                        End If
                    Next
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub btnView_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnView.Click, mnuView.Click
        Try
            Const MAXREC As Integer = 5000
            Dim dt As DataTable = Nothing
            Dim TableName As String = Me.lstTables.SelectedItem
            If Not Project.ResetPDox(TableName) Then Exit Sub
            Dim NumRec As Integer = Project.DB.GetRecordCount(TableName)
            TaskStart(String.Format("Getting data for {0}", TableName))
            With New frmTableViewer
                With .dgTable
                    .DefaultCellStyle.NullValue = "<Null>"
                    Dim Sql As String
                    Select Case Project.DB.DatabaseType
                        Case clsDB.enumDBType.Firebird, clsDB.enumDBType.Firebird_Embedded
                            Sql = String.Format("SELECT FIRST {1} * from {0}", Project.DB.FullTableName(TableName), MAXREC)
                        Case clsDB.enumDBType.SQLite, clsDB.enumDBType.MySQL
                            Sql = String.Format("SELECT * from {0} LIMIT {1}", Project.DB.FullTableName(TableName), MAXREC)
                        Case clsDB.enumDBType.Oracle
                            Sql = String.Format("SELECT * from {0} WHERE CAST(ROWNUM AS INTEGER)<={1}", Project.DB.FullTableName(TableName), MAXREC)
                        Case Else
                            Sql = String.Format("SELECT TOP {1} * from {0}", Project.DB.FullTableName(TableName), MAXREC)
                    End Select
                    Project.DB.AddTable(dt, Sql)
                    .DataSource = dt

                    'if table contains blob field, this must be removed before opening the form or will get formatting error
                    If .Columns.Contains("Object_Value") Then .Columns("Object_Value").Visible = False

                    .AutoSize = True
                End With
                .Text = String.Format("WRDB Table Viewer: {0} (First {1} of {2} records)", TableName, Min(NumRec, MAXREC), NumRec)
                MainForm.ProgressComplete()
                TaskEnd()
                .ShowDialog(Me)
                .Dispose()
                dt.Dispose()
            End With
            Project.ResetPDox()
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            MainForm.ProgressComplete()
            TaskEnd()
        End Try
    End Sub

    Private Sub btnDisplayDuplicates_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDisplayDups.Click, mnuDisplayDups.Click
        Try
            If Project.DB.IsPrimaryKeyRequired Then WarningMsg("This routine is not available for this type of data provider.") : Exit Sub
            Dim dt As DataTable = Nothing
            Dim TableName As String = Me.lstTables.SelectedItem
            With New frmSelectFields(TableName, "Display Duplicate Records", "&Fields (checked to use in comparison):")
                Dim Ignored As New Generic.List(Of String)
                Ignored.AddRange(New String() {"VALIDATED", "TRACK_ID", "CREATE_UPDATE"})
                For i As Integer = 0 To .lstFields.Items.Count - 1
                    If Not Ignored.Contains(.lstFields.Items(i)) Then .lstFields.SetItemChecked(i, True)
                Next
                If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                    Dim fields As String = ""
                    For i As Integer = 0 To .lstFields.Items.Count - 1
                        If .lstFields.GetItemChecked(i) Then fields &= IIf(fields = "", "", ",") & .lstFields.Items(i)
                    Next
                    TaskStart(String.Format("Finding duplicates in {0}", TableName))
                    If Not Project.ResetPDox(TableName) Then Exit Sub
                    With New frmTableViewer
                        With .dgTable
                            .DefaultCellStyle.NullValue = "<Null>"
                            Dim Sql As String = String.Format("SELECT {0},Count(*) as Num_Duplicates FROM {1} GROUP BY {0} HAVING Count(*)>1 ORDER BY {0}", fields, TableName)
                            Project.DB.AddTable(dt, Sql)
                            .DataSource = dt
                            For i As Integer = 0 To dt.Columns.Count - 1
                                If dt.Columns(i).DataType Is GetType(Byte()) Then
                                    .Columns(i).Visible = False
                                    Dim dgcol As New DataGridViewLinkColumn
                                    dgcol.HeaderText = .Columns(i).HeaderText
                                    dgcol.DefaultCellStyle.NullValue = ""
                                    .Columns.Add(dgcol)
                                End If
                            Next
                            .AutoSize = True
                        End With
                        .Text = String.Format("WRDB Table Viewer: Duplicate records in {0}", TableName)
                        MainForm.ProgressComplete()
                        If dt.Rows.Count = 0 Then
                            WarningMsgFmt("No duplicate records exist in the selected table: {0}.", TableName)
                        Else
                            .ShowDialog(Me)
                        End If
                        TaskEnd()
                        .Dispose()
                        dt.Dispose()
                    End With
                End If
                .Dispose()
            End With
        Catch ex As DbSqlException
            ErrorMsg("NOTE: because this command can take a long time to execute, it may be necessary to increase the command timeout setting at the bottom of the form.", ex)
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            MainForm.ProgressComplete()
            TaskEnd()
        End Try
    End Sub


    Private Sub btnIndices_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnIndices.Click, mnuIndices.Click
        Try
            With Project.DB
                Dim lasttimeout As Integer = .CommandTimeout
                Try
                    Dim TableName As String = lstTables.Text
                    If .DatabaseType = clsDB.enumDBType.Paradox And Project.GetTableType(TableName) <= clsProject.enumTableTypes.Master Then
                        If .IsTableIndexed(TableName) Then
                            If WarningMsg("This Paradox data table is currently fully compatible with WRDB 5.x and all operations can be performed on the table. However, performance for queries and graphing is likely to be relatively poor.\n\nDo you want to change this table to make it read-only to improve performance?") = Windows.Forms.DialogResult.OK Then
                                .UpgradeTableBruteForce(TableName, Project.GetTableTemplate(clsProject.enumTableTypes.Working), False)
                            End If
                        Else
                            If WarningMsg("This Paradox data table is currently in a semi read-only state associated with legacy and new unmodified tables. Although you can import data into this table one time and perform fast queries and graphing of the data, you are prevented from performing many operations on the table.\n\nDo you want to upgrade this table to make it fully functional in WRDB 5.0?") = Windows.Forms.DialogResult.OK Then
                                .UpgradeTableBruteForce(TableName, Project.GetTableTemplate(clsProject.enumTableTypes.Working), True)
                            End If
                        End If
                    Else
                        If Project.GetTableType(TableName) <= clsProject.enumTableTypes.Master Then
                            If Not MainForm.CheckDataTableStructure(TableName, False) Then Exit Sub
                        Else
                            If Not MainForm.CheckTableStructure(TableName) Then Exit Sub
                        End If
                        With New frmSelectFields(TableName, "Manage Table Indices", "&Fields (checked if indexed):")
                            Dim lstIndexColumns As Generic.List(Of String) = Project.DB.GetIndexList(TableName)
                            For i As Integer = 0 To .lstFields.Items.Count - 1
                                If lstIndexColumns.Contains(.lstFields.Items(i)) Then .lstFields.SetItemChecked(i, True)
                            Next
                            If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                                TaskStart("Creating and/or removing indices; please be patient...")
                                Project.DB.CommandTimeout = 10 * 60 'ten minute timeout
                                Dim lstIndices As Generic.List(Of String) = Project.DB.GetIndexList(TableName)
                                With .lstFields
                                    For i As Integer = 0 To .Items.Count - 1
                                        Dim ColumnName As String = .Items(i)
                                        Dim Action As enumIndexAction = enumIndexAction.None
                                        Dim found As Boolean = lstIndices.Contains(ColumnName)
                                        If .GetItemChecked(i) Then
                                            If Not found Then Action = enumIndexAction.Create
                                        Else
                                            If found Then Action = enumIndexAction.Drop
                                        End If

                                        Select Case Action
                                            Case enumIndexAction.Create : Project.DB.CreateIndex(TableName, ColumnName, Project.GetTableTemplate(clsProject.enumTableTypes.Working))
                                            Case enumIndexAction.Drop : Project.DB.DropIndex(TableName, ColumnName, Project.GetTableTemplate(clsProject.enumTableTypes.Temporary))
                                        End Select

                                        'following frees up UI but is really slow!!!!

                                        'If Action <> enumIndexAction.None Then
                                        '    bwExecuteNonQuery = New System.ComponentModel.BackgroundWorker
                                        '    bwExecuteNonQuery.RunWorkerAsync(New Object() {Action, TableName, ColumnName})
                                        '    While bwExecuteNonQuery.IsBusy
                                        '        Threading.Thread.Sleep(500)
                                        '        Application.DoEvents()
                                        '    End While
                                        '    bwExecuteNonQuery.Dispose()
                                        'End If
                                        If Project.DB.Cancelled Then Exit For
                                        If Project.DB.DatabaseType = clsDB.enumDBType.Paradox And Action = enumIndexAction.Drop Then
                                            WarningMsg("All indices have been removed from the Paradox table; please repeat the command and add back any indices you want to keep.")
                                            Exit For
                                        End If
                                    Next
                                End With
                            End If
                            .Dispose()
                        End With
                    End If
                Catch ex As Exception
                    ErrorMsg(, ex)
                Finally
                    Project.DB.CommandTimeout = lasttimeout
                    TaskEnd()
                End Try
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub bwExecuteNonQuery_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwExecuteNonQuery.DoWork
        Dim Action As enumIndexAction = e.Argument(0)
        Dim TableName As String = e.Argument(1)
        Dim ColumnName As String = e.Argument(2)
        Select Case Action
            Case enumIndexAction.Create : Project.DB.CreateIndex(TableName, ColumnName, Project.GetTableTemplate(clsProject.enumTableTypes.Working))
            Case enumIndexAction.Drop : Project.DB.DropIndex(TableName, ColumnName, Project.GetTableTemplate(clsProject.enumTableTypes.Temporary))
        End Select
        e.Result = True
    End Sub

    Private Sub bwExecuteNonQuery_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwExecuteNonQuery.RunWorkerCompleted
        If e.Result = -2 Then ErrorMsg("Unable to execute SQL string.", QuerySQL, e.Error)
    End Sub

    Private Sub cboTableType_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboTableType.SelectedIndexChanged
        FillTableList()
    End Sub

    Private Sub EnableButtons()
        Try
            With Me.lstTables.SelectedItems
                btnCopy.Enabled = .Count >= 1
                mnuCopy.Enabled = .Count = 1
                btnCopyFrom.Enabled = True
                mnuCopyFrom.Enabled = True
                btnDelete.Enabled = .Count >= 1
                mnuDelete.Enabled = .Count >= 1
                btnDeleteRecords.Enabled = .Count = 1
                mnuDeleteRecords.Enabled = .Count = 1
                btnChange.Enabled = .Count = 1
                mnuChange.Enabled = .Count = 1
                btnDeleteDups.Enabled = .Count = 1 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                mnuDeleteDups.Enabled = .Count = 1 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                btnDisplayDups.Enabled = .Count = 1 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                mnuDisplayDups.Enabled = .Count = 1 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                btnCompare.Enabled = .Count = 2 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                mnuCompare.Enabled = .Count = 2 And (Me.cboTableType.Text.Contains("Working") Or Me.cboTableType.Text.Contains("Master"))
                btnRename.Enabled = .Count = 1 And Not Me.cboTableType.Text.Contains("Support")
                mnuRename.Enabled = .Count = 1
                btnView.Enabled = .Count = 1
                mnuView.Enabled = .Count = 1
                btnUpgrade.Enabled = .Count >= 1
                mnuUpgrade.Enabled = .Count >= 1
                btnImport.Enabled = .Count = 1
                mnuImport.Enabled = .Count = 1
                btnExport.Enabled = .Count >= 1
                mnuExport.Enabled = .Count >= 1
                btnArchive.Enabled = .Count >= 1
                mnuArchive.Enabled = .Count >= 1
                btnIndices.Enabled = .Count = 1
                mnuIndices.Enabled = .Count = 1
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub EnableCntls(ByVal Parent As Control, ByVal Enable As Boolean)
        Try
            For Each cntl As Control In Parent.Controls
                If Not (cntl Is lnkProgress Or cntl Is btnClose) Then
                    cntl.Enabled = Enable
                    EnableCntls(cntl, Enable)
                End If
            Next
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub TaskEnd()
        Try
            UpdateDBInfo()
            MainForm.ProgressComplete()
            EnableCntls(Me, True)
            btnClose.Text = "Close"
            EnableButtons()
            lnkProgress.Visible = False
            Me.Cursor = Cursors.Default
            Application.DoEvents()
            'Application.UseWaitCursor = False
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub FillTableList()
        Try
            MainForm.WriteProgress("Getting table list")
            If Not Project.ResetPDox(CType(Choose(cboTableType.SelectedIndex + 1, clsProject.enumTableTypes.Working, clsProject.enumTableTypes.Stations, clsProject.enumTableTypes.Working), clsProject.enumTableTypes)) Then Exit Sub
            Me.lstTables.Items.Clear()
            For Each s As String In Project.DB.GetTableList()
                Dim TblType As clsProject.enumTableTypes = Project.GetTableType(s)
                If cboTableType.Text.StartsWith("All") OrElse _
                    (cboTableType.Text.StartsWith("Working") And TblType = clsProject.enumTableTypes.Working) OrElse _
                    (cboTableType.Text.StartsWith("Master") And TblType = clsProject.enumTableTypes.Master) OrElse _
                    (cboTableType.Text.StartsWith("Support") And TblType >= clsProject.enumTableTypes.Stations And TblType <= clsProject.enumTableTypes.Tracking) Then
                    Me.lstTables.Items.Add(s)
                End If
            Next
            Me.btnCopy.Enabled = False
            Me.btnCopyFrom.Enabled = True
            Me.btnDelete.Enabled = False
            Me.btnChange.Enabled = False
            Me.btnRename.Enabled = False
            Me.btnView.Enabled = False
            EnableButtons()
            MainForm.ProgressComplete()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub frmDBExplorer_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveWindowPos(REGAPP, Me)
        SaveSetting(REGAPP, "DBExplorer", "LastSQL", txtSQL.Text)
        SaveSetting(REGAPP, "DBExplorer", "Timeout", Project.DB.CommandTimeout)
        Project.DB.CommandTimeout = PriorTimeout
    End Sub

    Private Sub frmDBExplorer_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            With Project
                UpdateDBInfo()
                PriorTimeout = Project.DB.CommandTimeout
                Project.DB.CommandTimeout = GetSetting(REGAPP, "DBExplorer", "Timeout", PriorTimeout)
                GetWindowPos(REGAPP, Me)
                With Me.cboTableType
                    .Items.Add("Working Tables")
                    .Items.Add("Master Tables")
                    .Items.Add("Support Tables")
                    .Items.Add("All Tables")
                    .SelectedIndex = 0
                End With
                If Not Project.DB.OpenConnection Then Exit Sub
                Dim dt As DataTable = Project.DB.Connection.GetSchema("MetaDataCollections")
                Project.DB.Connection.Close()
                For Each rec As DataRow In dt.Rows
                    Me.lstSchemaCollection.Items.Add(rec.Item("CollectionName"))
                Next
                dt.Dispose()
                dt = Nothing
            End With

            btnCompact.Enabled = True
            mnuCompact.Enabled = True

            'always enable so can purge temp views and tables

            'Select Case Project.DB.DatabaseType
            '    Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.Firebird, clsDB.enumDBType.Paradox, clsDB.enumDBType.SQLite
            '        btnCompact.Enabled = True
            '        mnuCompact.Enabled = True
            '    Case Else
            '        btnCompact.Enabled = False
            '        mnuCompact.Enabled = False
            'End Select

            txtSQL.Text = GetSetting(REGAPP, "DBExplorer", "LastSQL", "")
            With dgResults
                .ReadOnly = True
                .AllowUserToOrderColumns = False
                .AllowUserToResizeColumns = True
                .AllowUserToResizeRows = False
                .AllowUserToAddRows = False
                .AllowUserToDeleteRows = False
                .RowHeadersVisible = False
                .SelectionMode = DataGridViewSelectionMode.FullRowSelect
                dgvResults = New WRDB.Controls.DGVEditor(dgResults)
            End With
        Catch ex As DbSqlException
            WarningMsg(ex.Message)
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub UpdateDBInfo()
        With Project
            Dim dbName As String = "", dbType As String = "", dbSize As String = "", LastUpdated As String = ""
            Select Case .DB.DatabaseType
                Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite
                    dbName = My.Computer.FileSystem.GetName(.DB.DataSource)
                    dbSize = String.Format("Size: {0:0} Mb; ", My.Computer.FileSystem.GetFileInfo(.DB.DataSource).Length / 1000000.0)
                    LastUpdated = String.Format("Updated: {0:MM/dd/yyyy HH:mm}; ", My.Computer.FileSystem.GetFileInfo(.DB.DataSource).LastWriteTime)
                Case Else
                    dbName = .DB.DatabaseName
                    dbSize = ""
            End Select
            dbType = .DB.DatabaseType.ToString
            lblDatabaseInfo.Text = String.Format("Database Name: {0}; Type: {1}; {2}{3}No. Tables: {4}", dbName, dbType, dbSize, LastUpdated, Project.GetTableListAll.Count)
        End With
    End Sub

    Private Sub lnkProgress_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkProgress.LinkClicked
        AskCancel()
        Project.DB.Cancelled = ProgressCancel
    End Sub

    Private Sub lstSchemaCollection_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstSchemaCollection.SelectedIndexChanged, cboTableType.SelectedIndexChanged
        Try
            TaskStart("Refreshing grid...")
            If lstSchemaCollection.SelectedIndex = -1 Then Exit Sub
            If Not Project.ResetPDox(CType(Choose(cboTableType.SelectedIndex + 1, clsProject.enumTableTypes.Working, clsProject.enumTableTypes.Stations, clsProject.enumTableTypes.Working), clsProject.enumTableTypes)) Then Exit Sub
            If Not Project.DB.OpenConnection Then Exit Sub
            If Project.DB.DatabaseType = clsDB.enumDBType.SQL_Server_CE Then
                Dim dt As DataTable = Nothing
                Project.DB.AddTable(dt, "SELECT * FROM Information_Schema." & lstSchemaCollection.SelectedItem.ToString)
                Me.dgSchemaTable.DataSource = dt
            Else
                Me.dgSchemaTable.DataSource = Project.DB.Connection.GetSchema(Me.lstSchemaCollection.SelectedItem.ToString)
            End If
            Me.dgSchemaTable.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
            Me.dgSchemaTable.AutoSize = True
            Project.DB.Connection.Close()
        Catch ex As DbSqlException
            WarningMsg(ex.Message)
        Catch ex As Exception
            WarningMsg("An error occurred while trying to examine the database format, which indicates that either you don't have sufficient permissions on this database or the database is corrupted; use the Compact/Repair feature to correct this problem.", , ex)
        Finally
            TaskEnd()
        End Try
    End Sub

    Private Sub lstTables_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lstTables.MouseDoubleClick
        Me.btnView.PerformClick()
    End Sub

    Private Sub lstTables_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstTables.SelectedIndexChanged, cboTableType.SelectedIndexChanged
        EnableButtons()
    End Sub

    Friend Sub TaskStart(ByVal ProgressText As String)
        Try
            EnableCntls(Me, False)
            btnClose.Text = "Cancel"
            lnkProgress.Text = ProgressText & " (click here to cancel)..."
            lnkProgress.Visible = True
            Project.DB.Cancelled = False
            'Application.UseWaitCursor = True
            Me.Cursor = Cursors.WaitCursor
            Application.DoEvents()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub TabControl1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TabControl1.SelectedIndexChanged
        Select Case TabControl1.SelectedIndex
            Case 0 : AcceptButton = btnView
            Case 1 : AcceptButton = btnExecute
            Case 2 : AcceptButton = Nothing
        End Select
    End Sub

    Private Sub btnHelp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHelp.Click
        ShowHelp(Me, "7")
    End Sub

    Private Sub lnkTimeout_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkTimeout.LinkClicked
        Dim s As String = InputBox("To allow longer execution times for these commands, enter new command timeout value in seconds:", "Command Timeout", Project.DB.CommandTimeout)
        If Val(s) > 0 Then Project.DB.CommandTimeout = Val(s)
    End Sub

    Private Sub dgResults_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgResults.CellFormatting
        'If Project.DB.DatabaseType = clsDB.enumDBType.SQL_Server Then 'for some reason, does not obey datagridview nullvalue setting
        '    If dgResults.Item(e.ColumnIndex, e.RowIndex).Value.isnull Then e.Value = "<Null>" : e.FormattingApplied = True
        'End If
    End Sub

    Private Sub dgResults_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles dgResults.DataError
        If Not ErrorAlreadyDisplayed Then
            ErrorMsg("An error occurred while trying to display the results.", e.Exception)
        End If
        ErrorAlreadyDisplayed = True
    End Sub

    Private Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSearch.Click, mnuSearch.Click
        MainForm.EditSearchTables()
    End Sub

    Private Sub btnFilter_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFilter.Click
        Try
            Static FilterString As String = ""
            With New frmFilter
                .DataGrid = dgSchemaTable
                .txtFilterString.Text = FilterString
                .ShowDialog(Me)
                FilterString = .txtFilterString.Text
                'Dim bsSchema = New BindingSource(dgSchemaTable.DataSource, dgSchemaTable.DataMember)
                'dgSchemaTable.DataSource = bsSchema
                'bsSchema.Filter = FilterString
                .Dispose()
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
        With New OpenFileDialog
            .AddExtension = True
            .AutoUpgradeEnabled = True
            .CheckFileExists = True
            .CheckPathExists = True
            .DefaultExt = ".sqldb"
            .Filter = "WRDB Database Explorer SQL (*.sqldb)|*.sqldb"
            .InitialDirectory = AppDataPath
            .Multiselect = False
            If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                txtSQL.Text = IO.File.ReadAllText(.FileName)
            End If
        End With
    End Sub

    Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
        With New SaveFileDialog
            .AddExtension = True
            .AutoUpgradeEnabled = True
            .CheckPathExists = True
            .DefaultExt = ".sqldb"
            .Filter = "WRDB Database Explorer SQL (*.sqldb)|*.sqldb"
            .InitialDirectory = AppDataPath
            If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                IO.File.WriteAllText(.FileName, txtSQL.Text)
            End If
        End With
    End Sub
End Class

Public Class BlobFormatProvider
    Implements System.IFormatProvider, ICustomFormatter

    Public Function GetFormat(ByVal formatType As System.Type) As Object Implements System.IFormatProvider.GetFormat
        If formatType Is GetType(ICustomFormatter) Then
            Return Me
        Else
            Return Nothing
        End If
    End Function

    Public Function Format(ByVal fmt As String, ByVal arg As Object, ByVal formatProvider As IFormatProvider) As String Implements ICustomFormatter.Format
        If arg Is Nothing Then Return "NOTHING" Else Return "SOMETHING"
    End Function
End Class
